#include "higerCC1101.h"

/**************************************************************************************************
 * @fn          Mrfi_CalculateRssi
 *
 * @brief       Does binary to decimal conversiont and offset compensation.
 *
 * @param       none
 *
 * @return      RSSI value in units of dBm.
 **************************************************************************************************
 */
#define MRFI_RSSI_OFFSET    79   /* no units */
int8_t Mrfi_CalculateRssi(uint8_t rawValue)
{
  int16_t rssi;

  /* The raw value is in 2's complement and in half db steps. Convert it to
   * decimal taking into account the offset value.
   */
  if(rawValue >= 128)
  {
    rssi = (int16_t)(rawValue - 256)/2 - MRFI_RSSI_OFFSET;
  }
  else
  {
    rssi = (rawValue/2) - MRFI_RSSI_OFFSET;
  }

  /* Restrict this value to least value can be held in an 8 bit signed int */
  if(rssi < -128)
  {
    rssi = -128;
  }

  return rssi;
}

/**************************************************************************************************
 * @fn          MRFI_Rssi
 *
 * @brief       Returns "live" RSSI value
 *
 * @param       none
 *
 * @return      RSSI value in units of dBm.
 **************************************************************************************************
 */
int8_t MRFI_Rssi(void)
{
  uint8_t regValue;

//  /* Radio must be in RX state to measure rssi. */
//  MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX );

//  /* Wait for the RSSI to be valid:
//   * Just having the Radio ON is not enough to read
//   * the correct RSSI value. The Radio must in RX mode for
//   * a certain duration. This duration depends on
//   * the baud rate and the received signal strength itself.
//   */
//#ifdef MRFI_TIMER_ALWAYS_ACTIVE
//  MRFI_WaitTimeoutUsec(MRFI_RSSI_VALID_DELAY_US, Mrfi_ValidateRSSI);
//#else // MRFI_TIMER_ALWAYS_ACTIVE
//  MRFI_RSSI_VALID_WAIT();
//#endif // MRFI_TIMER_ALWAYS_ACTIVE

  /* Read the RSSI value */
  regValue = halSpiReadReg( CCxxx0_RSSI );

  /* convert and do offset compensation */
  return( Mrfi_CalculateRssi(regValue) );
}


/* ------------------------------------------------------------------------------------------------
 *                                           Macros
 * ------------------------------------------------------------------------------------------------
 */
void Mrfi_RxModeOn(void)
{
    /* clear any residual receive interrupt */
    MRFI_CLEAR_SYNC_PIN_INT_FLAG();

    /* send strobe to enter receive mode */
    halSpiStrobe( CCxxx0_SRX );

    /* enable receive interrupts */
    MRFI_ENABLE_SYNC_PIN_INT();
}
/**************************************************************************************************
 * @fn          Mrfi_RxModeOff
 *
 * @brief       -
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
static void Mrfi_RxModeOff(void)
{
    /*disable receive interrupts */
    MRFI_DISABLE_SYNC_PIN_INT();

    /* turn off radio */
    MRFI_STROBE_IDLE_AND_WAIT();

    /* flush the receive FIFO of any residual data */
    halSpiStrobe( CCxxx0_SFRX );

    /* clear receive interrupt */
    MRFI_CLEAR_SYNC_PIN_INT_FLAG();
}

/**************************************************************************************************
 * @fn          MRFI_PrepareToTx
 *
 * @brief       Setup fifo and other variables for transmit
 *
 * @param       pPacket - pointer to packet to transmit
 *
 * @return      None
 **************************************************************************************************
 */
static void MRFI_PrepareToTx( uint8_t * pucData )
{

    halSpiStrobe( CCxxx0_SFTX ); // flush the tx fifo

    {
        /* compute number of bytes to write to transmit FIFO */
        uint8_t txBufLen = (pucData[0] + 1);
        halSpiWriteBurstReg( pucData, txBufLen );
    }

}

///**************************************************************************************************
// * @fn          MRFI_DelayMs
// *
// * @brief       Delay the specified number of milliseconds.
// *
// * @param       milliseconds - delay time
// *
// * @return      none
// **************************************************************************************************
// */
//void MRFI_DelayMs(uint16_t milliseconds)
//{
//    while (milliseconds)
//    {
//        Mrfi_DelayUsec( APP_USEC_VALUE );
//        milliseconds--;
//    }
//}

/* Worst case wait period in RX state before RSSI becomes valid.
 * These numbers are from Design Note DN505 with added safety margin.
 */
#define MRFI_RSSI_VALID_DELAY_US    1300


/* There is no bit in h/w to tell if RSSI in the register is valid or not.
 * The hardware needs to be in RX state for a certain amount of time before
 * a valid RSSI value is calculated and placed in the register. This min
 * wait time is defined by MRFI_BOARD_RSSI_VALID_DELAY_US. We don't need to
 * add such delay every time RSSI value is needed. If the Carier Sense signal
 * is high or CCA signal is high, we know that the RSSI value must be valid.
 * We use that knowledge to reduce our wait time. We break down the delay loop
 * in multiple chunks and during each iteration, check for the CS and CCA
 * signal. If either of these signals is high, we return immediately. Else,
 * we wait for the max delay specified.
 */
#define MRFI_RSSI_VALID_WAIT()                                                \
{                                                                             \
    int16_t delay = MRFI_RSSI_VALID_DELAY_US;                                   \
    uint32_t ucDelayUs = 0x280;                                                    \
    do                                                                          \
{                                                                           \
    if(halSpiReadReg(CCxxx0_PKTSTATUS) & (MRFI_PKTSTATUS_CCA | MRFI_PKTSTATUS_CS))  \
{                                                                         \
    break;                                                                  \
    }                                                                         \
    ucDelayUs = 0x280;                                                       \
    while(ucDelayUs--);                                                      \
    delay -= 64;                                                              \
    }while(delay > 0);                                                          \
    }                                                                             \
    //    Mrfi_DelayUsec(64); /* sleep */ use while(ucDelayUs--); take the same use 64us

static void Mrfi_RxModeOn(void);
static uint8_t spiBurstFifoAccess(uint8_t addrByte, uint8_t * pData, uint8_t len);
uint8_t mrfiSpiReadRxFifo(uint8_t * pData, uint8_t len);
static void Mrfi_SyncPinRxIsr(void);
void MRFI_RxCompleteISR(void);


/* return values for MRFI_Transmit */
#define MRFI_TX_RESULT_SUCCESS        0
#define MRFI_TX_RESULT_FAILED         1

unsigned long portGetTickCnt(void);

uint8_t MRFI_Transmit(uint8_t *pPacket, uint8_t txType)
{
    uint8_t ccaRetries;
    uint8_t returnValue = MRFI_TX_RESULT_SUCCESS;

    /* Turn off reciever. We can ignore/drop incoming packets during transmit. */
    Mrfi_RxModeOff();

    MRFI_PrepareToTx( pPacket );

    /* ------------------------------------------------------------------
   *    Immediate transmit
   *   ---------------------
   */
    if (txType == MRFI_TX_TYPE_FORCED)
    {
           /* Issue the TX strobe. */
        halSpiStrobe( CCxxx0_STX );
             /* Wait for transmit to complete */
        //                Mrfi_DelayUsecLong( MRFI_MAX_TRANSMIT_TIME_us / 1000,
        //                                    MRFI_MAX_TRANSMIT_TIME_us % 1000,
        //                                    mrfi_TxImmediateDone );
        while (!MRFI_SYNC_PIN_INT_FLAG_IS_SET());

        /* Clear the interrupt flag */
        MRFI_CLEAR_SYNC_PIN_INT_FLAG();
    }
    else
    {
        /* ------------------------------------------------------------------
         *    CCA transmit
         *   ---------------
         */

        /* set number of CCA retries */
        ccaRetries = MRFI_CCA_RETRIES;

        /* For CCA algorithm, we need to know the transition from the RX state to
         * the TX state. There is no need for SYNC signal in this logic. So we
         * can re-configure the GDO_0 output from the radio to be PA_PD signal
         * instead of the SYNC signal.
         * Since both SYNC and PA_PD are used as falling edge interrupts, we
         * don't need to reconfigure the MCU input.
         */
        MRFI_CONFIG_GDO0_AS_PAPD_SIGNAL();

        /* ===============================================================================
         *    Main Loop
         *  =============
         */
        for (;;)
        {
            /* Radio must be in RX mode for CCA to happen.
           * Otherwise it will transmit without CCA happening.
           */

            /* Can not use the Mrfi_RxModeOn() function here since it turns on the
           * Rx interrupt, which we don't want in this case.
           */
            halSpiStrobe( CCxxx0_SRX );

            /* wait for the rssi to be valid. */

            MRFI_RSSI_VALID_WAIT();

            /*
           *  Clear the PA_PD pin interrupt flag.  This flag, not the interrupt itself,
           *  is used to capture the transition that indicates a transmit was started.
           *  The pin level cannot be used to indicate transmit success as timing may
           *  prevent the transition from being detected.  The interrupt latch captures
           *  the event regardless of timing.
           */
            MRFI_CLEAR_PAPD_PIN_INT_FLAG();

            /* Issue the TX strobe. */
            halSpiStrobe( CCxxx0_STX );

            /* Delay long enough for the PA_PD signal to indicate a
           * successful transmit. This is the 250 XOSC periods
           * (9.6 us for a 26 MHz crystal) See section 19.6 of 2500 datasheet.
           * Found out that we need a delay of atleast 20 us on CC2500 and
           * 25 us on CC1100 to see the PA_PD signal change.
           */
            //            Mrfi_DelayUsec(25);
            CC_delay(25);

            /* PA_PD signal goes from HIGH to LOW when going from RX state.
           * This transition is trapped as a falling edge interrupt flag
           * to indicate that CCA passed and the transmit has started.
           */
            if (MRFI_PAPD_INT_FLAG_IS_SET())
            {
                /* ------------------------------------------------------------------
            *    Clear Channel Assessment passed.
            *   ----------------------------------
            */

                /* Clear the PA_PD int flag */
                MRFI_CLEAR_PAPD_PIN_INT_FLAG();

                //                Mrfi_DelayUsecLong( MRFI_MAX_TRANSMIT_TIME_us / 1000,
                //                                    MRFI_MAX_TRANSMIT_TIME_us % 1000,
                //                                    mrfi_TxCCADone );
                while (!(MRFI_PAPD_PIN_IS_HIGH()));
                /* transmit done, break */
                break;
            }
            else
            {
                /* ------------------------------------------------------------------
             *    Clear Channel Assessment failed.
             *   ----------------------------------
             */

                /* Turn off radio and save some power during backoff */

                /* NOTE: Can't use Mrfi_RxModeOff() - since it tries to update the
             * sync signal status which we are not using during the TX operation.
             */
                MRFI_STROBE_IDLE_AND_WAIT();

                /* flush the receive FIFO of any residual data */
                halSpiStrobe( CCxxx0_SFRX );

                /* Retry ? */
                if (ccaRetries != 0)
                {
                    /* delay for a random number of backoffs */
                    //                    Mrfi_RandomBackoffDelay();
                    CC_delay(1000*((portGetTickCnt()%16)));

                    MRFI_PrepareToTx( pPacket ); // setup transmission again

                    /* decrement CCA retries before loop continues */
                    ccaRetries--;
                }
                else /* No CCA retries are left, abort */
                {
                    /* set return value for failed transmit and break */
                    returnValue = MRFI_TX_RESULT_FAILED;
                    break;
                }
            } /* CCA Failed */
        } /* CCA loop */
    }/* txType is CCA */

    /* Done with TX. Clean up time... */

    /* Radio is already in IDLE state */

    /*
       * Flush the transmit FIFO.  It must be flushed so that
       * the next transmit can start with a clean slate.
       */
    halSpiStrobe( CCxxx0_SFTX );

    /* Restore GDO_0 to be SYNC signal */
    MRFI_CONFIG_GDO0_AS_SYNC_SIGNAL();

    /* If the radio was in RX state when transmit was attempted,
           * put it back to Rx On state.
           */
    //    if(mrfiRadioState == MRFI_RADIO_STATE_RX)
    {
        Mrfi_RxModeOn();
    }

    return( returnValue );
}

/**************************************************************************************************
 * @fn          MRFI_GpioIsr
 *
 * @brief       Interrupt Service Routine for handling GPIO interrupts.  The sync pin interrupt
 *              comes in through GPIO.  This function is designed to be compatible with "ganged"
 *              interrupts.  If the GPIO interrupt services more than just a single pin (very
 *              common), this function just needs to be called from the higher level interrupt
 *              service routine.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void MRFI_GpioIsr(void)
{

    /* see if sync pin interrupt is enabled and has fired */
    //
    if (MRFI_SYNC_PIN_INT_IS_ENABLED() && MRFI_SYNC_PIN_INT_FLAG_IS_SET())
    {
        /*  clear the sync pin interrupt, run sync pin ISR */

        /*
     *  NOTE!  The following macro clears the interrupt flag but it also *must*
     *  reset the interrupt capture.  In other words, if a second interrupt
     *  occurs after the flag is cleared it must be processed, i.e. this interrupt
     *  exits then immediately starts again.  Most microcontrollers handle this
     *  naturally but it must be verified for every target.
     */
        MRFI_CLEAR_SYNC_PIN_INT_FLAG();
        Mrfi_SyncPinRxIsr();
        Mrfi_RxModeOn();
    }
}

/**************************************************************************************************
 * @fn          Mrfi_SyncPinRxIsr
 *
 * @brief       This interrupt is called when the SYNC signal transition from high to low.
 *              The sync signal is routed to the sync pin which is a GPIO pin.  This high-to-low
 *              transition signifies a receive has completed.  The SYNC signal also goes from
 *              high to low when a transmit completes.   This is protected against within the
 *              transmit function by disabling sync pin interrupts until transmit completes.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
static void Mrfi_SyncPinRxIsr( void )
{
    uint8_t frameLen = 0x00;
    uint8_t rxBytes;

    /* We should receive this interrupt only in RX state
   * Should never receive it if RX was turned On only for
   * some internal mrfi processing like - during CCA.
   * Otherwise something is terribly wrong.
   */
    //    MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX );

    /* ------------------------------------------------------------------
   *    Get RXBYTES
   *   -------------
   */

    /*
   *  Read the RXBYTES register from the radio.
   *  Bit description of RXBYTES register:
   *    bit 7     - RXFIFO_OVERFLOW, set if receive overflow occurred
   *    bits 6:0  - NUM_BYTES, number of bytes in receive FIFO
   *
   *  Due a chip bug, the RXBYTES register must read the same value twice
   *  in a row to guarantee an accurate value.
   */
    {
        uint8_t rxBytesVerify;

        do
        {
            rxBytes = rxBytesVerify;
            rxBytesVerify = halSpiReadReg( CCxxx0_RXBYTES );
        }
        while (rxBytes != rxBytesVerify);
    }


    /* ------------------------------------------------------------------
       *    FIFO empty?
       *   -------------
       */

    /*
       *  See if the receive FIFIO is empty before attempting to read from it.
       *  It is possible nothing the FIFO is empty even though the interrupt fired.
       *  This can happen if address check is enabled and a non-matching packet is
       *  received.  In that case, the radio automatically removes the packet from
       *  the FIFO.
       */
    if (rxBytes == 0)
    {
        /* receive FIFO is empty - do nothing, skip to end */
    }
    else
    {
        /* receive FIFO is not empty, continue processing */

        /* ------------------------------------------------------------------
         *    Process frame length
         *   ----------------------
         */

        /* read the first byte from FIFO - the packet length */
        mrfiSpiReadRxFifo(&frameLen, MRFI_LENGTH_FIELD_SIZE);

        /*
         *  Make sure that the frame length just read corresponds to number of bytes in the buffer.
         *  If these do not match up something is wrong.
         *
         *  This can happen for several reasons:
         *   1) Incoming packet has an incorrect format or is corrupted.
         *   2) The receive FIFO overflowed.  Overflow is indicated by the high
         *      bit of rxBytes.  This guarantees the value of rxBytes value will not
         *      match the number of bytes in the FIFO for overflow condition.
         *   3) Interrupts were blocked for an abnormally long time which
         *      allowed a following packet to at least start filling the
         *      receive FIFO.  In this case, all received and partially received
         *      packets will be lost - the packet in the FIFO and the packet coming in.
         *      This is the price the user pays if they implement a giant
         *      critical section.
         *   4) A failed transmit forced radio to IDLE state to flush the transmit FIFO.
         *      This could cause an active receive to be cut short.
         *
         *  Also check the sanity of the length to guard against rogue frames.
         */

#ifdef CC_BASE
        if (frameLen != sizeof(slaveToBaseCmdDataDef))
#else
        if (frameLen != sizeof(baseToSlaveCmdDataDef))
#endif
        {
            //            bspIState_t s;

            /* mismatch between bytes-in-FIFO and frame length */

            /*
           *  Flush receive FIFO to reset receive.  Must go to IDLE state to do this.
           *  The critical section guarantees a transmit does not occur while cleaning up.
           */
            //            BSP_ENTER_CRITICAL_SECTION(s);
            MRFI_STROBE_IDLE_AND_WAIT();
            halSpiStrobe( CCxxx0_SFRX );
            //            halSpiStrobe( CCxxx0_SRX );
            //            BSP_EXIT_CRITICAL_SECTION(s);

            /* flush complete, skip to end */
        }
        else
        {
            /* bytes-in-FIFO and frame length match up - continue processing */

            /* ------------------------------------------------------------------
           *    Get packet
           *   ------------
           */

            /* clean out buffer to help protect against spurious frames */
            //            memset(mrfiIncomingPacket.frame, 0x00, sizeof(mrfiIncomingPacket.frame));

            /* set length field */
            //            mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFS] = frameLen;

            /* get packet from FIFO */
            //            mrfiSpiReadRxFifo(&(mrfiIncomingPacket.frame[MRFI_FRAME_BODY_OFS]), frameLen);

            /* get receive metrics from FIFO */
            //            mrfiSpiReadRxFifo(&(mrfiIncomingPacket.rxMetrics[0]), MRFI_RX_METRICS_SIZE);

            //            mrfiSpiReadRxFifo((&(slaveToBaseCmd.ucDatalen) + 1), (frameLen - 1));
            slaveToBaseCmd.ucDatalen = frameLen;
#ifdef CC_BASE
            mrfiSpiReadRxFifo((&(slaveToBaseCmd.tSl2BCmdData.ucTransmitID)), frameLen);
#else
            mrfiSpiReadRxFifo((&(baseToSlaveCmd.tB2SlCmdData.ucTransmitID)), frameLen);
#endif
            mrfiSpiReadRxFifo(tCmdMertric.ucData, 2);
            MRFI_DISABLE_SYNC_PIN_INT( ); // disable radio sync interrupt so no more occur
            //            rx_isr_context = true;        // deactivate sync pin interrupt enable/disable macros
            //            BSP_ENABLE_INTERRUPTS( );     // enable interrupts so higher priority irqs can occur

            /* ------------------------------------------------------------------
           *    CRC check
           *   ------------
           */

            /*
           *  Note!  Automatic CRC check is not, and must not, be enabled.  This feature
           *  flushes the *entire* receive FIFO when CRC fails.  If this feature is
           *  enabled it is possible to be reading from the FIFO and have a second
           *  receive occur that fails CRC and automatically flushes the receive FIFO.
           *  This could cause reads from an empty receive FIFO which puts the radio
           *  into an undefined state.
           */

            /* determine if CRC failed */
            //            if (!(mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] & MRFI_RX_METRICS_CRC_OK_MASK))
            if (!(tCmdMertric.ucData[1] & MRFI_RX_METRICS_CRC_OK_MASK))
            {
                /* CRC failed - do nothing, skip to end */
            }
            else
            {
                /* CRC passed - continue processing */

                /* ------------------------------------------------------------------
             *    Filtering
             *   -----------
             */

                /* if address is not filtered, receive is successful */
#ifdef CC_BASE
                if ( ( slaveToBaseCmd.tSl2BCmdData.usBaseAddr == ADDR_BASE ) || ( slaveToBaseCmd.tSl2BCmdData.tAgreementType == SENDSEARCHNET ) )
#else
                if ( baseToSlaveCmd.tB2SlCmdData.usDevAddr == deviceAddr )
#endif
                {
                    /* ------------------------------------------------------------------
                 *    Receive successful
                 *   --------------------
                 */

                    //                        /* Convert the raw RSSI value and do offset compensation for this radio */
                    //                        mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] =
                    //                                Mrfi_CalculateRssi(mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS]);

                    //                        /* Remove the CRC valid bit from the LQI byte */
                    //                        mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] =
                    //                                (mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] & MRFI_RX_METRICS_LQI_MASK);


                    //                        /* call external, higher level "receive complete" processing routine */
                    tCmdMertric.cRssi = MRFI_Rssi();
                    MRFI_RxCompleteISR();
                }
                //            }
            }
            //            BSP_DISABLE_INTERRUPTS( );    // disable interrupts so we can enable radio sync interrupt again
            //            rx_isr_context = false;       // activate sync pin interrupt enable/disable macros
            //            MRFI_ENABLE_SYNC_PIN_INT( );  // enable radio sync interrupt again
        }
    }

    /* ------------------------------------------------------------------
   *    End of function
   *   -------------------
   */
}
/******************************************************************************
 * @fn          MRFI_RxCompleteISR
 *
 * @brief       Here on Rx interrupt from radio. Process received frame from the
 *              radio Rx FIFO.
 *
 * input parameters
 *
 * output parameters
 *
 * @return      void
 */
void MRFI_RxCompleteISR()
{
    recvOkAndHandle();
}
/**************************************************************************************************
 * @fn          macSpiReadRxFifo
 *
 * @brief       Read data from radio receive FIFO.
 *
 * @param       pData - pointer for storing read data
 * @param       len   - length of data in bytes
 *
 * @return      true if an interrupt was detected during the transfer, false otherwise
 **************************************************************************************************
 */

uint8_t mrfiSpiReadRxFifo(uint8_t * pData, uint8_t len)
{
    return spiBurstFifoAccess(CCxxx0_RXFIFO | CCxxx0_BURST_BIT | CCxxx0_READ_BIT, pData, len);
}


/*=================================================================================================
 * @fn          spiBurstFifoAccess
 *
 * @brief       Burst mode access used for reading or writing to radio FIFOs.
 *
 *              For more efficient interrupt latency, this function does not keep interrupts
 *              disabled for its entire execution.  It is designed to recover if an interrupt
 *              occurs that accesses SPI.  See comments in code for further details.
 *
 * @param       addrByte - first byte written to SPI, contains address and mode bits
 * @param       pData    - pointer to data to read or write
 * @param       len      - length of data in bytes
 *
 * @return      true if an interrupt was detected during the transfer, false otherwise
 *=================================================================================================
 */

static uint8_t spiBurstFifoAccess(uint8_t addrByte, uint8_t * pData, uint8_t len)
{
    uint8_t result = ERROR; // initialize to successful status

    //  /* disable interrupts that use SPI */
    //  MRFI_SPI_ENTER_CRITICAL_SECTION(s);
    NVIC_CC1101GD0(DISABLE);

    //  /* turn chip select "off" and then "on" to clear any current SPI access */
    //  MRFI_SPI_TURN_CHIP_SELECT_OFF();
    //  MRFI_SPI_TURN_CHIP_SELECT_ON();

    CC_CSN_SELECT_OFF();
    CC_CSN_SELECT_ON();

    while (CC_MI_IS_HIGH() );
    /*-------------------------------------------------------------------------------
   *  Main loop.  If the SPI access is interrupted, execution comes back to
   *  the start of this loop.  Loop exits when nothing left to transfer.
   */
    do
    {
        //        /* send FIFO access command byte, wait for SPI access to complete */
        //        MRFI_SPI_WRITE_BYTE(addrByte);
        //        MRFI_SPI_WAIT_DONE();

        SPI_ExchangeByte(addrByte);

        /*-------------------------------------------------------------------------------
     *  Inner loop.  This loop executes as long as the SPI access is not interrupted.
     *  Loop completes when nothing left to transfer.
     */
        do
        {
            //            MRFI_SPI_WRITE_BYTE(*pData);

            /*-------------------------------------------------------------------------------
       *  Use idle time.  Perform increment/decrement operations before pending on
       *  completion of SPI access.
       *
       *  Decrement the length counter.  Wait for SPI access to complete.
       */
            //            len--;
            //            MRFI_SPI_WAIT_DONE();

            /*-------------------------------------------------------------------------------
       *  SPI data register holds data just read.  If this is a read operation,
       *  store the value into memory.
       */
            if (addrByte & CCxxx0_READ_BIT)
            {
                //                *pData = MRFI_SPI_READ_BYTE();

                *pData = SPI_ExchangeByte(*pData);
            }
            len--;

            /*-------------------------------------------------------------------------------
       *  At least one byte of data has transferred.  Briefly enable (and then disable)
       *  interrupts that can call SPI functions.  This provides a window for any timing
       *  critical interrupts that might be pending.
       *
       *  To improve latency, take care of pointer increment within the interrupt
       *  enabled window.
       */
            //            MRFI_SPI_EXIT_CRITICAL_SECTION(s);
            pData++;
            //            MRFI_SPI_ENTER_CRITICAL_SECTION(s);

            /*-------------------------------------------------------------------------------
       *  If chip select is "off" the SPI access was interrupted (all SPI access
       *  functions leave chip select in the "off" state).  In this case, turn
       *  back on chip select and break to the main loop.  The main loop will
       *  pick up where the access was interrupted.
       */
            //            if (MRFI_SPI_CHIP_SELECT_IS_OFF())
            //            {
            //                MRFI_SPI_TURN_CHIP_SELECT_ON();
            //                result = true;   // indicate interruption detected
            //                break;
            //            }

            /*-------------------------------------------------------------------------------
     */
        } while (len); /* inner loop */
    } while (len);   /* main loop */


    /* turn off chip select; enable interrupts that call SPI functions */

    //    MRFI_SPI_TURN_CHIP_SELECT_OFF();
    //    MRFI_SPI_EXIT_CRITICAL_SECTION(s);

    CC_CSN_SELECT_OFF();

    return result;
}


/**************************************************************************************************
 * @fn          Mrfi_RxModeOn
 *
 * @brief       Put radio into receive mode.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */


#ifdef CC_BASE
void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line10) != RESET) {
        MRFI_GpioIsr();
    }
}
#endif
